package com.erp.gather.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.erp.gather.domain.*;
import com.erp.gather.domain.bo.ErpSellerStoreProductInfringingKeywordsBo;
import com.erp.gather.domain.dto.ErpInfringingKeywordsDTO;
import com.erp.gather.domain.vo.ErpSellerStoreProductInfringingKeywordsVo;
import com.erp.gather.mapper.*;
import com.erp.gather.service.IErpSellerStoreProductInfringingKeywordsService;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.oldUtils.StringUtils;
import com.ruoyi.common.core.web.oldPage.TableDataInfo;
import com.ruoyi.common.redis.utils.RedisUtils;
import com.ruoyi.gather.api.domain.ErpCollectProduct;
import com.ruoyi.gather.api.domain.ErpSellerStoreProduct;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 商品侵权词Service业务层处理
 *
 * @author erp
 * @date 2023-12-06
 */
@RequiredArgsConstructor
@Service
public class ErpSellerStoreProductInfringingKeywordsServiceImpl implements IErpSellerStoreProductInfringingKeywordsService {

    private final ErpSellerStoreProductInfringingKeywordsMapper baseMapper;
    private final ErpSellerStoreProductInfringingKeywordsRecordMapper erpSellerStoreProductInfringingKeywordsRecordMapper;
    private final ErpCollectProductMapper erpCollectProductMapper;
    private final ErpCollectProductExpandMapper erpCollectProductExpandMapper;
    private final ErpSellerStoreProductMapper erpSellerStoreProductMapper;
    private final ErpSellerStoreProductInfringingKeywordsExceptionsMapper erpSellerStoreProductInfringingKeywordsExceptionsMapper;

    private static Map<String, Object> keywordsMap;
    private static String path = "D:\\testingReport\\";
//    private static String path = "/pb/erp-admin/testingReport";

    /**
     * 查询商品侵权词
     */
    @Override
    public ErpSellerStoreProductInfringingKeywordsVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询商品侵权词列表
     */
    @Override
    public TableDataInfo<ErpSellerStoreProductInfringingKeywordsVo> queryPageList(ErpSellerStoreProductInfringingKeywordsBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ErpSellerStoreProductInfringingKeywords> lqw = buildQueryWrapper(bo);
        Page<ErpSellerStoreProductInfringingKeywordsVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询商品侵权词列表
     */
    @Override
    public List<ErpSellerStoreProductInfringingKeywordsVo> queryList(ErpSellerStoreProductInfringingKeywordsBo bo) {
        LambdaQueryWrapper<ErpSellerStoreProductInfringingKeywords> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ErpSellerStoreProductInfringingKeywords> buildQueryWrapper(ErpSellerStoreProductInfringingKeywordsBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ErpSellerStoreProductInfringingKeywords> lqw = Wrappers.lambdaQuery();
        lqw.like(bo.getKeywordText() != null, ErpSellerStoreProductInfringingKeywords::getKeywordText, bo.getKeywordText());
        lqw.like(StringUtils.isNotBlank(bo.getKeywordMemo()), ErpSellerStoreProductInfringingKeywords::getKeywordMemo, bo.getKeywordMemo());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), ErpSellerStoreProductInfringingKeywords::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增商品侵权词
     */
    @Override
    public Boolean insertByBo(ErpSellerStoreProductInfringingKeywordsBo bo) {
        ErpSellerStoreProductInfringingKeywords add = BeanUtil.toBean(bo, ErpSellerStoreProductInfringingKeywords.class);
        validEntityBeforeSave(add);
        add.setStatus(0);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改商品侵权词
     */
    @Override
    public Boolean updateByBo(ErpSellerStoreProductInfringingKeywordsBo bo) {
        ErpSellerStoreProductInfringingKeywords update = BeanUtil.toBean(bo, ErpSellerStoreProductInfringingKeywords.class);
        validEntityBeforeSave(update);
        update.setStatus(0);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ErpSellerStoreProductInfringingKeywords entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除商品侵权词
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public R<Object> keyWordsDetection(Integer type, Long id) {
        //获取所有的关键词
        Map<String, Object> keyWordsNowMap = getKeyWordsNowMap();
        ErpCollectProduct collectProduct = erpCollectProductMapper.selectById(id);
        ErpSellerStoreProduct sellerStoreProduct = erpSellerStoreProductMapper.selectById(id);
        Map<String, Object> abnormalTextMap = new HashMap<>();

        if (type == 1) {
            //采集商品库 详情
            abnormalTextMap = getKeyWordsNowMap(collectProduct.getDetail(), keyWordsNowMap);
        } else if (type == 2) {
            //采集商品库 标题
            abnormalTextMap = getKeyWordsNowMap(collectProduct.getSubject(), keyWordsNowMap);
        } else if (type == 3) {
            //在线商品库 标题
            abnormalTextMap = getKeyWordsNowMap(sellerStoreProduct.getDetail(), keyWordsNowMap);
        } else if (type == 4) {
            //在线商品库 标题
            abnormalTextMap = getKeyWordsNowMap(sellerStoreProduct.getSubject(), keyWordsNowMap);
        }

        if (ObjectUtils.isEmpty(abnormalTextMap)) {
            return R.fail("商品查询对应数据为空");
        } else {
            return R.ok(abnormalTextMap);
        }
    }

    public Map<String, Object> getKeyWordsNowMap(String text, Map<String, Object> keyWordsNowMap) {
        Map<String, Object> abnormalTextMap = new HashMap<>();
        //如果详情不为空
        if (ObjectUtils.isEmpty(text)) {
            return null;
        }
        //将详情分割为每句
        List<String> detailList = Arrays.asList(text.split("[.!?:,;]+\\s*|\\n"));
        for (String detail : detailList) {
            detail = detail.trim();
            for (Map.Entry<String, Object> entry : keyWordsNowMap.entrySet()) {
                if (!detail.toLowerCase().contains(" " + entry.getKey().toLowerCase() + " ")) {
                    //如果不包含则跳过
                    continue;
                } else {
                    //若包含，则判断是否包含于例外情况
                    Boolean flag = true;
                    List<ErpSellerStoreProductInfringingKeywordsExceptions> exceptionsList = (List<ErpSellerStoreProductInfringingKeywordsExceptions>) entry.getValue();
                    for (ErpSellerStoreProductInfringingKeywordsExceptions exceptions : exceptionsList) {
                        String regex = "(?i).*" + Pattern.quote(exceptions.getExceptionsClause()) + ".*";
                        Pattern pattern = Pattern.compile(regex);
                        Matcher matcher = pattern.matcher(detail);
                        if (matcher.matches()) {
                            //是例外情况，跳过
                            flag = false;
                            break;
                        }
                    }
                    //不是例外情况，记录
                    if (flag) {
                        if (ObjectUtils.isEmpty(abnormalTextMap.get(detail))) {
                            abnormalTextMap.put(detail, entry.getKey());
                        } else {
                            abnormalTextMap.put(detail, abnormalTextMap.get(detail) + "|" + entry.getKey());
                        }
                    }
                }
            }
        }
        return abnormalTextMap;
    }


    @Override
    public Map<String, Object> getKeyWordsNowMap() {
        //看看是否有需要更新的
        List<ErpSellerStoreProductInfringingKeywords> keywordsWillUpdate = baseMapper.selectList(
                new LambdaQueryWrapper<ErpSellerStoreProductInfringingKeywords>()
                        .eq(ErpSellerStoreProductInfringingKeywords::getStatus, 0)
                        .or()
                        .eq(ErpSellerStoreProductInfringingKeywords::getStatus, -1)
        );
        List<ErpSellerStoreProductInfringingKeywordsExceptions> exceptionsWillUpdate = erpSellerStoreProductInfringingKeywordsExceptionsMapper.selectList(
                new LambdaQueryWrapper<ErpSellerStoreProductInfringingKeywordsExceptions>()
                        .eq(ErpSellerStoreProductInfringingKeywordsExceptions::getStatus, 0)
                        .or()
                        .eq(ErpSellerStoreProductInfringingKeywordsExceptions::getStatus, -1)
        );
        if (keywordsWillUpdate.size() == 0 && exceptionsWillUpdate.size() == 0) {
            //没有需要更新的
            return RedisUtils.getCacheMap("keywordsNowMap");
        } else {
            //将所有侵权词变为1
            ErpSellerStoreProductInfringingKeywords updateKeywords = new ErpSellerStoreProductInfringingKeywords();
            updateKeywords.setStatus(1);
            baseMapper.update(updateKeywords, new LambdaQueryWrapper<ErpSellerStoreProductInfringingKeywords>().eq(ErpSellerStoreProductInfringingKeywords::getStatus, 0));

            //将所有侵权词延展变为1
            ErpSellerStoreProductInfringingKeywordsExceptions updateExceptions = new ErpSellerStoreProductInfringingKeywordsExceptions();
            updateExceptions.setStatus(1);
            erpSellerStoreProductInfringingKeywordsExceptionsMapper.update(updateExceptions, new LambdaQueryWrapper<ErpSellerStoreProductInfringingKeywordsExceptions>().eq(ErpSellerStoreProductInfringingKeywordsExceptions::getStatus, 0));
        }

        //更新缓存
        List<ErpSellerStoreProductInfringingKeywords> keywordsList = baseMapper.selectList(
                new LambdaQueryWrapper<ErpSellerStoreProductInfringingKeywords>()
                        .eq(ErpSellerStoreProductInfringingKeywords::getStatus, 1)
        );

        Map<String, Object> keywordsNowMap = keywordsList.stream()
                .collect(Collectors.toMap(ErpSellerStoreProductInfringingKeywords::getKeywordText, ErpSellerStoreProductInfringingKeywords::getId));

        for (Map.Entry<String, Object> entry : keywordsNowMap.entrySet()) {
            List<ErpSellerStoreProductInfringingKeywordsExceptions> exceptionsList = erpSellerStoreProductInfringingKeywordsExceptionsMapper.selectList(
                    new LambdaQueryWrapper<ErpSellerStoreProductInfringingKeywordsExceptions>()
                            .select(ErpSellerStoreProductInfringingKeywordsExceptions::getExceptionsClause)
                            .eq(ErpSellerStoreProductInfringingKeywordsExceptions::getStatus, 1)
                            .eq(ErpSellerStoreProductInfringingKeywordsExceptions::getKeywordsId, entry.getValue())
            );

//            String exceptionsClause = exceptionsList.stream()
//                    .map(ErpSellerStoreProductInfringingKeywordsExceptions::getExceptionsClause)
//                    .collect(Collectors.joining(","));

            keywordsNowMap.put(entry.getKey(), exceptionsList);
        }
        //清除缓存
        RedisUtils.deleteObject("keywordsNowMap");

        //放入缓存
        RedisUtils.setCacheMap("keywordsNowMap", keywordsNowMap);
        return keywordsNowMap;

    }



    /**
     * 设置关键词状态
     *
     * @param keyWordsId
     * @param type
     * @return
     */
    @Override
    public R<Object> setKeyWordsStatus(Long keyWordsId, Integer type) {
        ErpSellerStoreProductInfringingKeywords keywords = baseMapper.selectById(keyWordsId);
        if (ObjectUtils.isEmpty(keywords)) {
            return R.fail("关键词不存在");
        }
        if (type == 1) {
            //启用
            keywords.setStatus(0);
        } else {
            //停用
            keywords.setStatus(-1);
        }
        if (baseMapper.updateById(keywords) > 0) {
            return R.ok("设置成功");
        } else {
            return R.fail("设置失败");
        }
    }

    /**
     * 公共产品库
     *
     * @param
     * @return
     */
    @Async
    @Override
    public void collectProductKeyWordsDetection(HttpServletResponse response, Integer type, Long userId) {

        List<ErpCollectProduct> collectProductIdList = new ArrayList<>();
        if (ObjectUtils.isEmpty(userId)) {
            collectProductIdList = erpCollectProductMapper.queryCollectProductIdList();
        } else {
            collectProductIdList = erpCollectProductMapper.queryCollectProductIdListByUserId(userId);
        }

        String fileName = new String();
        ErpSellerStoreProductInfringingKeywordsRecord record = new ErpSellerStoreProductInfringingKeywordsRecord();
        record.setType(type);
        record.setUserId(userId);
        if (collectProductIdList.size() == 0) {
            record.setRecordName("暂无需要鉴定侵权的品");
            record.setRecordUrl(null);
            record.setStatus(-1);
            erpSellerStoreProductInfringingKeywordsRecordMapper.insert(record);
            return;
        }

        //获取所有关键词
        Map<String, Object> keyWordsNowMap = getKeyWordsNowMap();
        Map<String, Object> resultMap = new HashMap<>();
        Map<Long, Object> resultAllMap = new HashMap<>();

        record.setStatus(0);
        if (type == 1 || type == 3) {
            //标题
            for (ErpCollectProduct product : collectProductIdList) {
                resultMap = getKeyWordsNowMap(product.getSubject(), keyWordsNowMap);
                if (ObjectUtils.isNotEmpty(resultMap) && resultMap.size() > 0) {
                    resultAllMap.put(product.getId(), resultMap);
                }
            }
            try {
                fileName = "标题 侵权检测 " + IdUtil.fastSimpleUUID().substring(0, 6);
                record.setRecordName(fileName);
                record.setRecordUrl(path + fileName + ".xlsx");
                erpSellerStoreProductInfringingKeywordsRecordMapper.insert(record);
                downloadToDisk(resultAllMap, fileName, "标题", path);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else if (type == 2 || type == 4) {
            //标题
            for (ErpCollectProduct product : collectProductIdList) {
                resultMap = getKeyWordsNowMap(product.getDetail(), keyWordsNowMap);
                if (ObjectUtils.isNotEmpty(resultMap) && resultMap.size() > 0) {
                    resultAllMap.put(product.getId(), resultMap);
                }
            }
            try {
                fileName = "详情 侵权检测 " + IdUtil.fastSimpleUUID().substring(0, 6);
                record.setRecordName(fileName);
                record.setRecordUrl(path + fileName + ".xlsx");
                erpSellerStoreProductInfringingKeywordsRecordMapper.insert(record);
                downloadToDisk(resultAllMap, fileName, "详情", path);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        record.setStatus(1);
        erpSellerStoreProductInfringingKeywordsRecordMapper.updateById(record);
    }

    @Override
    public List<String> selectKeywordText() {
        return baseMapper.selectKeywordText();
    }

    @Override
    public Date selectLastUpdateTime() {
        return baseMapper.selectLastUpdateTime();
    }

    @Override
    public R<Object> addTimes(Long id) {
        ErpSellerStoreProductInfringingKeywords keywords = baseMapper.selectById(id);
        keywords.setTimes(keywords.getTimes() + 1);
        int update = baseMapper.updateById(keywords);
        return update > 0? R.ok() : R.fail();
    }

    public void downloadToDisk(Map<Long, Object> resultAllMap, String fileName, String sheetName, String path) throws IOException {
        XSSFWorkbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet(sheetName);

        List<ErpInfringingKeywordsDTO> dtoList = new ArrayList<>();

        for (Map.Entry<Long, Object> entry : resultAllMap.entrySet()) {
            Map<String, Object> keyWordsNowMap = (Map<String, Object>) entry.getValue();
            for (Map.Entry<String, Object> abnormalText : keyWordsNowMap.entrySet()) {
                ErpInfringingKeywordsDTO dto = new ErpInfringingKeywordsDTO();
                dto.setCollectProductId(entry.getKey().toString());
                dto.setAbnormalStatement(abnormalText.getKey());
                dto.setKeyWords((String) abnormalText.getValue());
                dtoList.add(dto);
            }

        }

        int rowIndex = 0;
        for (ErpInfringingKeywordsDTO rowData : dtoList) {
            Row row = sheet.createRow(rowIndex++);
            int columnIndex = 0;
            for (int i = 0; i < 3; i++) {
                Cell cell = row.createCell(columnIndex++);
                switch (i) {
                    case 0:
                        cell.setCellValue(rowData.getCollectProductId());
                        break;
                    case 1:
                        cell.setCellValue(rowData.getAbnormalStatement());
                        break;
                    case 2:
                        cell.setCellValue(rowData.getKeyWords());
                        break;
                }
            }
        }

        FileOutputStream outputStream = new FileOutputStream(path + fileName + ".xlsx");
        System.out.println(fileName);

        workbook.write(outputStream);
        workbook.close();
        outputStream.close();


    }

}
